package com.emerquim.bean.dao;

import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

import org.apache.log4j.Logger;

import com.emerquim.persistence.dao.BaseHibernateDAO;


/**
 * Clase para retornar la conexion a la base de datos implementando
 * un singleton
 * @author Felipe Criales
 */
public class ConexionJDBC extends BaseHibernateDAO {
	
	/**
	 * Funcionalidad de log
	 */
	private static final Logger log = Logger.getLogger(ConexionJDBC.class);

	/**
	 * Singleton para la conexion a la base de datos
	 */
	private static ConexionJDBC singleton = null;
		
	/**
	 * Constructor de la clase privado para implementar el singleton
	 */
	private ConexionJDBC(){
		
	}
	
	/**
	 * Retorna el objeto singleton de la clase
	 * @return El objeto singleton
	 * @author Felipe Criales
	 */
	public static ConexionJDBC getSingleton() {
		if (singleton == null)
			singleton = new ConexionJDBC();
		return singleton;
	}
	
	/**
	 * Metodo para retornar la conexion con la base de datos
	 * @author Felipe Criales
	 */
	public Connection getConnection(){
		return this.getSession().connection();		
	}
	
	 /**
     * Quietly close the Connection. Any errors will be printed to the stderr.
     * @param connection The Connection to be closed quietly.
     */
    public static void close(Connection connection) {
        if (connection != null) {
            try {
                connection.close();
            } catch (SQLException e) {
                log.error("Closing Connection failed: " + e.getMessage());
                log.error("error",e);
            }
        }
    }
    
    /**
     * Metodo para ejecutar un query en la base de datos
     * @param query
     */
    public static void executeQuery(String query){
    	Connection conexion = null;
		try {
			conexion = ConexionJDBC.getSingleton().getConnection();		
			conexion.createStatement().execute(query);		
			conexion.commit();
		} catch (Exception e) {
			log.error("Error ejecutando la siguiente sentencia: " + query);
			e.printStackTrace();
		}
		finally {
			ConexionJDBC.close(conexion);
		}		
    }

    /**
     * Quietly close the Statement. Any errors will be printed to the stderr.
     * @param statement The Statement to be closed quietly.
     */
    public static void close(Statement statement) {
        if (statement != null) {
            try {
                statement.close();
            } catch (SQLException e) {
                log.error("Closing Statement failed: " + e.getMessage());
                log.error("error",e);
            }
        }
    }

    /**
     * Quietly close the ResultSet. Any errors will be printed to the stderr.
     * @param resultSet The ResultSet to be closed quietly.
     */
    public static void close(ResultSet resultSet) {
        if (resultSet != null) {
            try {
                resultSet.close();
                resultSet.close();
            } catch (SQLException e) {
                log.error("Closing ResultSet failed: ",e);
            }
        }
    }

    /**
     * Generate MD5 hash for the given String. MD5 is kind of an one-way encryption. Very useful for
     * hashing passwords before saving in database. This function generates exactly the same hash as
     * MySQL's own md5() function should do.
     * @param string The String to generate the MD5 hash for.
     * @return The 32-char hexadecimal MD5 hash of the given String.
     */
    public static String hashMD5(String string) {
        byte[] hash;

        try {
            hash = MessageDigest.getInstance("MD5").digest(string.getBytes("UTF-8"));
        } catch (NoSuchAlgorithmException e) {
            // Unexpected exception. "MD5" is just hardcoded and supported.
            throw new RuntimeException("MD5 should be supported?", e);
        } catch (UnsupportedEncodingException e) {
            // Unexpected exception. "UTF-8" is just hardcoded and supported.
            throw new RuntimeException("UTF-8 should be supported?", e);
        }

        StringBuilder hex = new StringBuilder(hash.length * 2);
        for (byte b : hash) {
            if ((b & 0xff) < 0x10) hex.append("0");
            hex.append(Integer.toHexString(b & 0xff));
        }
        return hex.toString();
    }
}
